GRID_INTERP
Overview
The GRID_INTERP function performs interpolation on a two-dimensional regular (rectilinear) grid, estimating values at arbitrary points based on known data defined at grid intersections. This is useful for applications such as lookup tables, surface modeling, and spatial data analysis where values need to be estimated between measured data points.
This implementation wraps SciPy’s RegularGridInterpolator class from the scipy.interpolate module. Unlike unstructured interpolation methods (such as LinearNDInterpolator), RegularGridInterpolator exploits the regular grid structure to avoid expensive triangulation, making it significantly faster for gridded data.
The function supports two interpolation methods:
- Linear interpolation: Performs bilinear interpolation by computing a weighted average of the four nearest grid points. For a point (x, y) within a grid cell bounded by points (x_1, y_1) and (x_2, y_2), the interpolated value is computed as:
f(x,y) \approx \frac{1}{(x_2-x_1)(y_2-y_1)} \bigl[ f(Q_{11})(x_2-x)(y_2-y) + f(Q_{21})(x-x_1)(y_2-y) + f(Q_{12})(x_2-x)(y-y_1) + f(Q_{22})(x-x_1)(y-y_1) \bigr]
- Nearest-neighbor interpolation: Returns the value of the closest grid point, useful when preserving discrete values is preferred over smooth interpolation.
The bounds_error parameter controls behavior for points outside the grid domain. When set to TRUE, an error is raised for out-of-bounds queries. When FALSE, the fill_value parameter specifies the value returned for such points (defaulting to NaN).
For more details on the underlying algorithm, see the SciPy documentation and the SciPy GitHub repository.
This example function is provided as-is without any representation of accuracy.
Excel Usage
=GRID_INTERP(points_x, points_y, values, xi, grid_interp_method, bounds_error, fill_value)
points_x(list[list], required): 1D array of x-coordinates of the grid pointspoints_y(list[list], required): 1D array of y-coordinates of the grid pointsvalues(list[list], required): 2D array of data values on the gridxi(list[list], required): Points at which to interpolate data (n_points, 2)grid_interp_method(str, optional, default: “linear”): Interpolation methodbounds_error(bool, optional, default: true): If True, raise error for out-of-bounds pointsfill_value(float, optional, default: null): Value for out-of-bounds points when bounds_error is False
Returns (list[list]): A 2D list of interpolated values, or an error message (str) if invalid.
Examples
Example 1: Demo case 1
Inputs:
| points_x | points_y | values | xi | ||||
|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 1 | 0.5 | 0.5 |
| 1 | 2 |
Excel formula:
=GRID_INTERP({0,1}, {0,1}, {0,1;1,2}, {0.5,0.5})
Expected output:
| Result |
|---|
| 1 |
Example 2: Demo case 2
Inputs:
| points_x | points_y | values | xi | grid_interp_method | |||||
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 0 | 1 | 1 | 2 | 0.4 | 0.6 | nearest |
| 3 | 4 | ||||||||
| 5 | 6 |
Excel formula:
=GRID_INTERP({0,1,2}, {0,1}, {1,2;3,4;5,6}, {0.4,0.6}, "nearest")
Expected output:
| Result |
|---|
| 2 |
Example 3: Demo case 3
Inputs:
| points_x | points_y | values | xi | ||||
|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
| 2 | 3 | 1 | 1 | ||||
| 0.5 | 0.5 |
Excel formula:
=GRID_INTERP({0,1}, {0,1}, {0,1;2,3}, {0,0;1,1;0.5,0.5})
Expected output:
| Result |
|---|
| 0 |
| 3 |
| 1.5 |
Example 4: Demo case 4
Inputs:
| points_x | points_y | values | xi | bounds_error | fill_value | ||||
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 1 | 2 | 0.5 | 0.5 | false | -999 |
| 3 | 4 | 1.5 | 1.5 |
Excel formula:
=GRID_INTERP({0,1}, {0,1}, {1,2;3,4}, {0.5,0.5;1.5,1.5}, FALSE, -999)
Expected output:
| Result |
|---|
| 2.5 |
| -999 |
Python Code
import math
import numpy as np
from scipy.interpolate import RegularGridInterpolator as scipy_RegularGridInterpolator
def grid_interp(points_x, points_y, values, xi, grid_interp_method='linear', bounds_error=True, fill_value=None):
"""
Interpolator on a regular grid in 2D.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.RegularGridInterpolator.html
This example function is provided as-is without any representation of accuracy.
Args:
points_x (list[list]): 1D array of x-coordinates of the grid points
points_y (list[list]): 1D array of y-coordinates of the grid points
values (list[list]): 2D array of data values on the grid
xi (list[list]): Points at which to interpolate data (n_points, 2)
grid_interp_method (str, optional): Interpolation method Valid options: Linear, Nearest. Default is 'linear'.
bounds_error (bool, optional): If True, raise error for out-of-bounds points Default is True.
fill_value (float, optional): Value for out-of-bounds points when bounds_error is False Default is None.
Returns:
list[list]: A 2D list of interpolated values, or an error message (str) if invalid.
"""
def to2d(x):
return [[x]] if not isinstance(x, list) else x
def flatten(arr):
return [item for sublist in arr for item in sublist]
# Normalize 2D list inputs
points_x = to2d(points_x)
points_y = to2d(points_y)
values = to2d(values)
xi = to2d(xi)
# Validate grid_interp_method parameter
valid_methods = ["linear", "nearest"]
if not isinstance(grid_interp_method, str):
return "Invalid input: grid_interp_method must be a string."
if grid_interp_method not in valid_methods:
return f"Invalid input: grid_interp_method must be one of {valid_methods}."
# Validate bounds_error parameter
if not isinstance(bounds_error, bool):
return "Invalid input: bounds_error must be a boolean."
# Validate fill_value parameter
if fill_value is not None:
try:
fill_value = float(fill_value)
if math.isnan(fill_value):
# NaN is allowed as fill_value
pass
elif math.isinf(fill_value):
return "Invalid input: fill_value must be finite or NaN."
except (TypeError, ValueError):
return "Invalid input: fill_value must be a number or None."
else:
fill_value = float("nan")
try:
# Flatten points_x and points_y
points_x_flat = flatten(points_x)
points_y_flat = flatten(points_y)
# Validate points are numeric
for i, val in enumerate(points_x_flat):
if not isinstance(val, (int, float)):
return f"Invalid input: points_x[{i}] must be numeric."
if math.isnan(val) or math.isinf(val):
return f"Invalid input: points_x[{i}] must be finite."
for i, val in enumerate(points_y_flat):
if not isinstance(val, (int, float)):
return f"Invalid input: points_y[{i}] must be numeric."
if math.isnan(val) or math.isinf(val):
return f"Invalid input: points_y[{i}] must be finite."
# Convert values to numpy array
values_arr = np.array(values, dtype=float)
# Validate values dimensions
if values_arr.ndim != 2:
return "Invalid input: values must be a 2D array."
if values_arr.shape[0] != len(points_x_flat):
return f"Invalid input: values must have shape ({len(points_x_flat)}, {len(points_y_flat)})."
if values_arr.shape[1] != len(points_y_flat):
return f"Invalid input: values must have shape ({len(points_x_flat)}, {len(points_y_flat)})."
# Convert xi to numpy array
xi_arr = np.array(xi, dtype=float)
# Validate xi dimensions
if xi_arr.ndim != 2:
return "Invalid input: xi must be a 2D array."
if xi_arr.shape[1] != 2:
return "Invalid input: xi must have shape (n_points, 2)."
# Create interpolator
points = (points_x_flat, points_y_flat)
interp = scipy_RegularGridInterpolator(
points,
values_arr,
method=grid_interp_method,
bounds_error=bounds_error,
fill_value=fill_value,
)
# Perform interpolation
result = interp(xi_arr)
# Convert result to 2D list (column vector)
return [[float(val)] for val in result]
except ValueError as e:
return f"Invalid input: {e}"
except Exception as e:
return f"scipy.interpolate.RegularGridInterpolator error: {e}"